﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using JetBrains.Annotations;
using SG.Productivity.DesktopControlPanel.Properties;

namespace SG.Productivity.DesktopControlPanel.Controls
{
    public partial class FiveStarControl : UserControl
    {
        private const decimal NumberOfStars = 5.0m;

        public FiveStarControl()
        {
            InitializeComponent();
        }

        private decimal _rating = 0.0m;

        [Category("Behavior")] 
        [Description("Fired when the rating is adjusted (previous != current)")]
        public event EventHandler<RatingChangedEventArgs> RatingChanged;
        
        [Category("Data")]
        [Description("From a scale from [0 .. <NumberOfStars = 5>] specify the rating")]
        public decimal Rating
        {
            get { return _rating; }

            set
            {
                if (value < 0.0m)
                    throw new ArgumentOutOfRangeException("value", value, Resources.FiveStarControl_Rating_MustGEQZero);

                if (value > NumberOfStars)
                    throw new ArgumentOutOfRangeException("value", value, Resources.FiveStarControl_Rating_MustBeSEQZero);

                if (value == _rating)
                    return;

                var previous = _rating;
                _rating = value;

                var fullStars = (int) (_rating%NumberOfStars);
                var remainder = _rating - fullStars;

                var starIndex = 0;
                for (; starIndex < fullStars; starIndex++)
                    this[starIndex].ImageIndex = 2;

                if (remainder >= 0.25m)
                    this[starIndex++].ImageIndex = remainder >= 0.75m ? 2 : 1;

                for (; starIndex < NumberOfStars; starIndex++)
                    this[starIndex].ImageIndex = 0;

                var ratingChanged = RatingChanged;
                if (ratingChanged != null)
                    ratingChanged(this, new RatingChangedEventArgs(previousValue: previous, @currentValue: _rating));
            }
        }

        private Button this[int starIndex]
        {
            get { return (Button) tableLayoutPanel1.GetControlFromPosition(starIndex, 0); }
        }

        private void StarClick(object sender, EventArgs args)
        {
            var star = (Control) sender;
            var mouseArgs = args as MouseEventArgs;

            if (mouseArgs != null)
                SetRatingFromMouseClick(star, mouseArgs);
        }

        private void SetRatingFromMouseClick([NotNull] Control star, [NotNull] MouseEventArgs mouseArgs)
        {
            var remainder = (mouseArgs.Location.X * 1.0m) / star.Width;
            var cell = tableLayoutPanel1.GetPositionFromControl(star);
            Rating = cell.Column + remainder;
        }

    }
}
